package com.agentframework.core.environment;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wangjun
 **/
class EnvironmentListeners {
    private static final Logger log = LoggerFactory.getLogger(EnvironmentListeners.class);

    private final List<EnvironmentEventListener<? extends EnvironmentEvent>> listeners;

    public EnvironmentListeners() {
        this.listeners = new ArrayList<>();
    }

    public void addListeners(@NonNull List<EnvironmentEventListener<?>> listeners) {
        this.listeners.addAll(listeners);
    }

    // 初始化事件
    public void init(AbstractEnvironment environment) {
        EnvironmentInitEvent event = new EnvironmentInitEvent(environment);
        doWithListeners("environment.init", event, EnvironmentInitEvent.class);
    }

    // 开始运行事件
    public void started(AbstractEnvironment environment) {
        EnvironmentStartedEvent event = new EnvironmentStartedEvent(environment);
        doWithListeners("environment.started", event, EnvironmentStartedEvent.class);
    }

    // 运行结束事件
    public void end(AbstractEnvironment environment) {
        EnvironmentEndEvent event = new EnvironmentEndEvent(environment);
        doWithListeners("environment.end", event, EnvironmentEndEvent.class);
    }

    // 错误事件
    public void error(AbstractEnvironment environment, Exception exception) {
        EnvironmentErrorEvent event = new EnvironmentErrorEvent(environment, exception);
        doWithListeners("environment.error", event, EnvironmentErrorEvent.class);
    }

    // 关闭事件
    public void shutdown(AbstractEnvironment environment) {
        EnvironmentShutdownEvent event = new EnvironmentShutdownEvent(environment);
        doWithListeners("environment.shutdown", event, EnvironmentShutdownEvent.class);
    }

    // 通用的事件处理方法
    private <E extends EnvironmentEvent> void doWithListeners(String eventName, E event, Class<E> eventType) {
        for (EnvironmentEventListener<? extends EnvironmentEvent> listener : listeners) {
            try {
                if (isListenerForEvent(listener, eventType)) {
                    log.debug("Publishing {} event to {}", eventName, listener.getClass().getName());
                    @SuppressWarnings("unchecked")
                    EnvironmentEventListener<E> typedListener = (EnvironmentEventListener<E>) listener;
                    typedListener.onEnvironmentEvent(event);
                }
            } catch (Exception ex) {
                log.error("Error in listener {} for event {}", listener.getClass().getName(), eventName, ex);
            }
        }
    }

    private <E extends EnvironmentEvent> boolean isListenerForEvent(EnvironmentEventListener<?> listener, Class<E> eventType) {
        Type[] genericInterfaces = listener.getClass().getGenericInterfaces();
        for (Type type : genericInterfaces) {
            if (type instanceof ParameterizedType parameterizedType) {
                if (parameterizedType.getRawType() == EnvironmentEventListener.class) {
                    Type actualType = parameterizedType.getActualTypeArguments()[0];
                    if (actualType instanceof Class) {
                        return eventType.isAssignableFrom((Class<?>) actualType);
                    }
                }
            }
        }
        return false;
    }

}
